import time
import os
from fpdf import FPDF
import sys
from typing import Union, List, Tuple


class PDFMaker:

    @staticmethod
    def make_pdf(result: dict, img_path: str, file_path_prefix: str = "tmp/pdf/"):
        """
        根据统计结果构造pdf
        :param result: 之前的统计结果
        :param img_path: 图片路径
        :param file_path_prefix: 用于保存临时文件的路径前缀
        :return: 临时pdf文件路径
        """
        if not os.path.isdir(file_path_prefix):
            os.makedirs(file_path_prefix)

        infoList = result["infoList"]
        dockedList = result["dockedList"]

        pdf = PDF()

        pdf.add_page()
        pdf.record_speed_interval(infoList)
        pdf.record_docked_info(dockedList)
        pdf.add_page()
        pdf.plot_route(img_path)
        pdf_path = file_path_prefix + str(int(time.time() * 1000)) + ".pdf"
        pdf.output(pdf_path)
        
        return pdf_path


class PDF(FPDF):
    def header(self):
        """
        标题
        :return:
        """
        self.set_font('Arial', 'B', 12)
        # self.cell(0, 10, 'Adding Text', 1, 1, 'C')

    def footer(self):
        """
        页脚
        :return:
        """
        self.set_y(-15)
        self.set_font('Arial', 'I', 8)
        self.cell(0, 10, 'Page %s' % self.page_no(), 0, 0, 'C')

    def content_width(self):
        """

        :return: 正文的宽度
        """
        return self.w - 2 * self.l_margin

    def record_speed_interval(self, infoList, col_width: Union[float, int, None] = None, cell_width_rate: Union[Tuple, List, None] = None):
        """
        将速度区间的数据画成表格
        :param infoList: 速度区间的数据
        :param col_width: 表格的总宽度
        :param cell_width_rate: 表格每列的比例
        :return:
        """
        if cell_width_rate is None:
            cell_width_rate = [1, 1, 1]
        rate_sum = sum(cell_width_rate)
        width = self.content_width()
        text_height = self.font_size * 1.2
        if not isinstance(col_width, float) and not isinstance(col_width, int):
            col_width = width / rate_sum
        else:
            col_width = min(float(col_width), width / rate_sum)

        self.set_font('Arial', 'B', 12)
        self.ln(text_height * 2)
        self.cell(width, text_height * 2, "Speed Distribution", align="C", border=1)
        self.ln(text_height * 2)

        self.cell(col_width * cell_width_rate[0], text_height, "Speed Interval", border=1)
        self.cell(col_width * cell_width_rate[1], text_height, "Rate", border=1)
        self.cell(col_width * cell_width_rate[2], text_height, "Time(hour)", border=1)
        self.ln(text_height)

        self.set_font('Arial', '', 12)
        sum_rate = 0
        sum_hours = 0
        for info in infoList[::-1]:
            startSpeed, endSpeed, totalSecond, rate = info["startSpeed"], info["endSpeed"], info["totalSecond"], \
                                                      info["rate"]
            hours = totalSecond / 3600
            sum_rate += rate
            sum_hours += hours
            # if endSpeed == sys.maxsize:
            #     endSpeed = startSpeed + 1
            # self.cell(col_width * cell_width_rate[0], text_height, f"[{int(startSpeed)}, {int(endSpeed)})", border=1)
            self.cell(col_width * cell_width_rate[0], text_height, f">= {int(startSpeed)}", border=1)
            self.cell(col_width * cell_width_rate[1], text_height, f"{sum_rate*100:.2f}%", border=1)
            self.cell(col_width * cell_width_rate[2], text_height, f"{sum_hours:.2f}", border=1)
            self.ln(text_height)

    def record_docked_info(self, infoList, col_width: Union[float, int, None] = None, list_posts_nums:int = 2, cell_width_rate: Union[Tuple, List, None] = None):
        """

        :param infoList: 停靠的信息
        :param col_width: 表格的总宽度
        :param list_posts_nums: 当前格式用不上
        :param cell_width_rate: 表格每列的比例
        :return:
        """
        if cell_width_rate is None:
            cell_width_rate = [0.1, 1, 1, 0.5]
        rate_sum = sum(cell_width_rate)
        width = self.content_width()
        text_height = self.font_size * 1.2
        if not isinstance(col_width, float) and not isinstance(col_width, int):
            col_width = width / rate_sum
        else:
            col_width = min(float(col_width), width / rate_sum)

        self.set_font('Arial', 'B', 12)
        self.ln(text_height * 2)
        self.cell(width, text_height * 2, "Ports Docked", align="C", border=1)
        self.ln(text_height * 2)

        self.cell(col_width * cell_width_rate[0], text_height, "id", border=1)
        self.cell(col_width * cell_width_rate[1], text_height, "Port Name", border=1)
        self.cell(col_width * cell_width_rate[2], text_height, "Position(latitude, longitude)", border=1)
        self.cell(col_width * cell_width_rate[3], text_height, "Time(hour)", border=1)
        self.ln(text_height)

        self.set_font('Arial', '', 12)
        infoList = sorted(infoList, key=lambda x: x["totalSeconds"], reverse=True)
        explains = []
        for i, info in enumerate(infoList):
            portId, portName, lat, lon, totalSeconds = info["portId"], info["portName"], info["lat"], info["lon"], \
                                                       info["totalSeconds"]
            ports = list(set(portName.split(";")))
            n = len(ports)
            portName = ports[0]

            # if n > 1:
            #     portName += "(" + ", ".join(ports[1:list_posts_nums])
            #     if n > list_posts_nums:
            #         portName += ", ..."
            #     portName += ")"
            if n > 1:
                portName += "*"
                names = ", ".join(ports)
                explain = f"* {names} have been considered as one port: {ports[0]}"
                explains.append(explain)

            hours = totalSeconds / 3600
            self.cell(col_width * cell_width_rate[0], text_height, f"{i + 1}", border=1)
            self.cell(col_width * cell_width_rate[1], text_height, f"{portName}", border=1)
            self.cell(col_width * cell_width_rate[2], text_height, f"({lat:.4f}, {lon:.4f})", border=1)
            self.cell(col_width * cell_width_rate[3], text_height, f"{hours:.2f}", border=1)
            self.ln(text_height)

        self.ln(text_height)

        for explain in explains:
            self.multi_cell(width, text_height, explain)
            self.ln(text_height)

    def plot_route(self, img_path: str):
        """

        :param img_path: 添加航线图
        :return:
        """
        width = self.content_width()
        text_height = self.font_size * 1.2
        self.set_font('Arial', 'B', 12)
        self.cell(width, text_height, "Route Chart: ")
        self.ln(text_height * 2)
        self.image(img_path, w=width)

